// 保存当前需收集的响应式函数
let activeReactiveFn = null


// 封装一个响应式的函数
class Depend {
  constructor() {
    this.reactiveFns = new Set()
  }

  notify() {
    this.reactiveFns.forEach(fn => {
      fn()
    })
  }
  depend() {
    if (activeReactiveFn) {
      this.reactiveFns.add(activeReactiveFn)
    }
  }
}

function watchFn(fn) {
  activeReactiveFn = fn
  fn()
  activeReactiveFn = null
}

// 封装一个获取depend函数
const targetMap = new WeakMap()

function getDepend(target, key) {
  // 根据target对象获取map的过程
  let map = targetMap.get(target)
  if (!map) {
    map = new Map()
    targetMap.set(target, map)
  }
  // 根据key获取真实的depend对象
  let depend = map.get(key)
  if (!depend) {
    depend = new Depend()
    map.set(key, depend)
  }
  return depend
}


// 
function reactive(obj) {
  // {name:'why',age:18}
  Object.keys(obj).forEach(key => {
    let value = obj[key]
    Object.defineProperty(obj, key, {
      get() {
        const depend = getDepend(obj, key)
        depend.depend()
        return value
      },
      set(newValue) {
        value = newValue
        const depend = getDepend(obj, key)
        depend.notify()
      }
    })
  })
  return obj
}


// 对象的响应式
const obj = {
  name: 'why', // new Depend 对应一个depend对象
  age: 18 // new Depend 对应一个depend对象
}

// 监听对象的属性变化:Proxy(vue2)/Object.defineProperty(vue)
const objProxy = reactive(obj)



const info = {
  address: '黄山市',
  height: 1.88
}

const infoProxy = reactive(info)


watchFn(() => {
  console.log(infoProxy.address);
})

infoProxy.address = '杭州市'



const fooProxy = reactive({ name: 'foo' })

watchFn(() => {
  console.log(fooProxy.name);
})

fooProxy.name = 'bar'